package com.ywz.framework.filter;

import cn.hutool.jwt.JWT;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ywz.common.JWTUtils;
import com.ywz.common.StringUtils;
import com.ywz.project.base.system.entity.TTenement;
import com.ywz.project.base.system.service.TTenementService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * 类描述 -> 切换数据源过滤器
 *
 * @Author: ywz
 * @Date: 2024/11/14
 */
@WebFilter(urlPatterns = "/*")
public class DynamicDataSourceFilter implements Filter {
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private TTenementService tenementService;
    @Value("${captcha.enabled}")
    private boolean captchaEnabled = false;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        DynamicDataSourceContextHolder.clear();
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String loginFlag = request.getParameter("loginFlag");
        if (!StringUtils.isEmpty(loginFlag) && loginFlag.equals("1")) {
            // 如果开启验证码功能则进入验证码校验
            if (captchaEnabled) {
                String captchaKey = request.getParameter("captchaKey");
                String captchaCode = request.getParameter("captchaCode");
                if (StringUtils.isEmpties(captchaKey, captchaCode)) {
                    respInfo(response, "验证码不能为空");
                    return;
                }
                String captcha = redisTemplate.opsForValue().get(captchaKey);
                if (StringUtils.isEmpty(captcha)) {
                    respInfo(response, "验证码已过期");
                    return;
                }
                if (!captcha.equalsIgnoreCase(captchaCode)) {
                    respInfo(response, "验证码错误");
                }
                // 验证码验证成功后删除验证码
                redisTemplate.delete(captcha);
            }
        }

        // 获取用户标识
        String username = request.getParameter("username");
        String token = request.getHeader("token");
        // 如果没有用户标识则从token中获取
        if (StringUtils.isEmpty(username) && !StringUtils.isEmpty(token)) {
            JWT tokenInfo = JWTUtils.getTokenInfo(token);
            username = tokenInfo.getPayload("username").toString();
        }

        // 如果没有用户标识则直接放行
        if (StringUtils.isEmpty(username)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }


        // 验证用户标识
        String[] s = username.split("_");
        // 如果是本部人员则直接放行
        if (s[0].equals("gy")) {
            DynamicDataSourceContextHolder.push("master");
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }

        // 如果是外部人员则根据用户标识切换数据源
        String key = "tenement_" + s[0];
        // 判断redis中是否存在该用户标识
        String time = redisTemplate.opsForValue().get(key);
        LocalDateTime now = LocalDateTime.now();
        if (!StringUtils.isEmpty(time)) {
            LocalDateTime parse = LocalDateTime.parse(time);
            if (now.isBefore(parse)) {
                // 如果在服务期内则切换数据源放行
                DynamicDataSourceContextHolder.push(s[0]);
                filterChain.doFilter(servletRequest, servletResponse);
            } else {
                // 如果超过服务期
                redisTemplate.opsForValue().set(key, time, 1, TimeUnit.DAYS);
                respInfo(response, "服务期已过，请联系管理员");
            }
        } else {
            // 切换主库
            DynamicDataSourceContextHolder.push("master");
            LambdaQueryWrapper<TTenement> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(TTenement::getIsDeleted, 0);
            queryWrapper.eq(TTenement::getTenantKey, s[0]);
            TTenement one = tenementService.getOne(queryWrapper, false);
            if (one == null) {
                respInfo(response, "客户不存在");
            } else {
                if (one.getStatus() == 1) {
                    redisTemplate.opsForValue().set(key, one.getServeTime().toString());
                    // 如果是正常状态则切换数据源放行
                    DynamicDataSourceContextHolder.push(s[0]);
                    filterChain.doFilter(servletRequest, servletResponse);
                } else {
                    respInfo(response, "客户已冻结");
                }

            }
        }
    }

    private void respInfo(HttpServletResponse response, String info) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        String json = "{\"code\":403,\"msg\":\"" + info + "\"}";
        PrintWriter writer = response.getWriter();
        writer.write(json);
        writer.close();
    }
}
